use std::{collections::HashMap, sync::Arc};

use rcu::RcuLock;

use crate::{protocol::MonitorProtocol, MonError, MonResult, Monitor, MonitorCommand, Protocol};

struct ReadlineProtocol {
    command_hash: Arc<RcuLock<HashMap<String, Arc<dyn MonitorCommand + Sync + Send>>>>,
}

impl MonitorCommand for ReadlineProtocol {
    fn mon_protocol_exec(&self, _: &Protocol) -> MonResult<Protocol> {
        Err(MonError::PermProtocol)
    }

    fn mon_readline_exec(
        &self,
        args: &HashMap<String, String>,
        printer: &crate::MonitorPrinter,
    ) -> MonResult<()> {
        let command = args.get("1").ok_or(MonError::InvalidArgsType)?;
        let lock = self.command_hash.read().unwrap();
        let data = lock.get(command).ok_or(MonError::NoCommand)?;

        let mut argss = vec![];
        for i in 1..args.len() {
            argss.push(args.get((i + 1).to_string().as_str()).unwrap().as_str());
        }

        let args_map = Monitor::readline_exec_get_hashmap(data, &argss)?;

        let protocol = MonitorProtocol::new(command, &args_map).to_json();
        printer.print(protocol.clone());
        let res = Monitor::protocol_exec_raw(self.command_hash.clone(), &protocol);
        printer.print(res);
        Ok(())
    }

    fn mon_readline_help(&self) -> String {
        String::from("在命令行使用 json 控制协议")
    }

    fn mon_readline_long_help(&self) -> Option<String> {
        Some(String::from(
            "使用如下格式在命令行使用 json 控制协议:
    protocol command arg1 arg2...",
        ))
    }
}

impl Monitor {
    // 注册 readline 控制协议执行
    //
    // 在命令行执行 json protocol, 通过此方式,
    // 可以验证命令的 json 控制协议执行结果以及现实控制协议内容.
    //
    // ```text
    // "protocol command arg1 arg2 arg3"
    // ```
    pub(crate) fn register_readline_protocol_exec(&self) {
        let rlp = Arc::new(ReadlineProtocol { command_hash: self.commnad_hash_clone() });
        self.register_command("protocol", rlp).unwrap();
    }
}
